/*****************************************************************************
 * hal_opl1x_uart.c
 *
 * Copyright (C) 2019 Jeasonvor <1101627719@qq.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 ****************************************************************************/

/*****************************************************************************
 * Included Files
 ****************************************************************************/

#include "plum_api.h"
#include "hal/source/hal_opl1x/hal_opl1x.h"

/*****************************************************************************
 * Trace Definitions
 ****************************************************************************/
#define LOG_RUN_LEVEL LOG_LEVEL_DEBUG
#define LOG_MODULE    "hal.uart"
#include "thirdparty/log/log.h"
/*****************************************************************************
 * Pre-processor Definitions
 ****************************************************************************/

/*****************************************************************************
 * Private Types
 ****************************************************************************/

/*****************************************************************************
 * Private Function Prototypes
 ****************************************************************************/

/*****************************************************************************
 * Private Data
 ****************************************************************************/

/*****************************************************************************
 * Public Data
 ****************************************************************************/

/*****************************************************************************
 * Private Functions
 ****************************************************************************/

PLUM_PRIVATE
E_UartIdx_t hal_opl1x_uart_idx(plum_u32 id)
{
    E_UartIdx_t idx = UART_IDX_MAX;

    switch (PLUM_HAL_UART_IDX(id)) {
#if defined(UART_IDX_0)
        case 0:
            idx = UART_IDX_0;
            break;
#endif

#if defined(UART_IDX_1)
        case 1:
            idx = UART_IDX_1;
            break;
#endif
        default:
            break;
    }

    return (idx);
}

PLUM_PRIVATE
E_UartDataBit_t hal_opl1x_uart_databits(plum_hal_uart_databit_t databits)
{
    E_UartDataBit_t dts = DATA_BIT_8;

    switch (databits) {
        case PLUM_HAL_UART_DATABIT_5:
            dts = DATA_BIT_5;
            break;
        case PLUM_HAL_UART_DATABIT_6:
            dts = DATA_BIT_6;
            break;
        case PLUM_HAL_UART_DATABIT_7:
            dts = DATA_BIT_7;
            break;
        case PLUM_HAL_UART_DATABIT_8:
            dts = DATA_BIT_8;
            break;
        case PLUM_HAL_UART_DATABIT_9:
        default:
            break;
    }

    return (dts);
}

PLUM_PRIVATE
E_UartParity_t hal_opl1x_uart_parity(plum_hal_uart_parity_t parity)
{
    E_UartParity_t pt = PARITY_NONE;

    switch (parity) {
        case PLUM_HAL_UART_PARITY_NONE:
            pt = PARITY_NONE;
            break;
        case PLUM_HAL_UART_PARITY_ODD:
            pt = PARITY_ODD;
            break;
        case PLUM_HAL_UART_PARITY_EVEN:
            pt = PARITY_EVEN;
            break;
        default:
            break;
    }

    return (pt);
}

PLUM_PRIVATE
E_UartFlowCtrl_t hal_opl1x_uart_flowctl(plum_hal_uart_flow_ctrl_t fctl)
{
    E_UartFlowCtrl_t flowctrl = UART_SIMPLE;

    switch (fctl) {
        case PLUM_HAL_UART_FLOW_CTRL_NONE:
            flowctrl = UART_SIMPLE;
            break;
        default:
            flowctrl = UART_FLOW;
            break;
    }

    return (flowctrl);
}

PLUM_PRIVATE
E_UartStopBit_t hal_opl1x_uart_stopbit(plum_hal_uart_stopbit_t stopbits)
{
    E_UartStopBit_t sb = STOP_BIT_1;

    switch (stopbits) {
        case PLUM_HAL_UART_STOPBIT_1:
            sb = STOP_BIT_1;
            break;
        case PLUM_HAL_UART_STOPBIT_1_5:
            sb = STOP_BIT_1P5;
            break;
        case PLUM_HAL_UART_STOPBIT_2:
            sb = STOP_BIT_2;
            break;
        case PLUM_HAL_UART_STOPBIT_0_5:
        default:
            break;
    }

    return (sb);
}

PLUM_PRIVATE
plum_u8 hal_opl1x_uart_gpio_pin(plum_u32 id)
{
    plum_u8 idx = BLANK_PIN;

    switch (PLUM_HAL_GPIO_PIN(id)) {
#if defined(OPL1000_IO0_PIN)
        case 0:
            idx = OPL1000_IO0_PIN;
            break;
#endif
#if defined(OPL1000_IO1_PIN)
        case 1:
            idx = OPL1000_IO1_PIN;
            break;
#endif
#if defined(OPL1000_IO2_PIN)
        case 2:
            idx = OPL1000_IO2_PIN;
            break;
#endif
#if defined(OPL1000_IO3_PIN)
        case 3:
            idx = OPL1000_IO3_PIN;
            break;
#endif
#if defined(OPL1000_IO4_PIN)
        case 4:
            idx = OPL1000_IO4_PIN;
            break;
#endif
#if defined(OPL1000_IO5_PIN)
        case 5:
            idx = OPL1000_IO5_PIN;
            break;
#endif
#if defined(OPL1000_IO6_PIN)
        case 6:
            idx = OPL1000_IO6_PIN;
            break;
#endif
#if defined(OPL1000_IO7_PIN)
        case 7:
            idx = OPL1000_IO7_PIN;
            break;
#endif
#if defined(OPL1000_IO8_PIN)
        case 8:
            idx = OPL1000_IO8_PIN;
            break;
#endif
#if defined(OPL1000_IO9_PIN)
        case 9:
            idx = OPL1000_IO9_PIN;
            break;
#endif
#if defined(OPL1000_IO10_PIN)
        case 10:
            idx = OPL1000_IO10_PIN;
            break;
#endif
#if defined(OPL1000_IO11_PIN)
        case 11:
            idx = OPL1000_IO11_PIN;
            break;
#endif
#if defined(OPL1000_IO12_PIN)
        case 12:
            idx = OPL1000_IO12_PIN;
            break;
#endif
#if defined(OPL1000_IO13_PIN)
        case 13:
            idx = OPL1000_IO13_PIN;
            break;
#endif
#if defined(OPL1000_IO14_PIN)
        case 14:
            idx = OPL1000_IO14_PIN;
            break;
#endif
#if defined(OPL1000_IO15_PIN)
        case 15:
            idx = OPL1000_IO15_PIN;
            break;
#endif
#if defined(OPL1000_IO16_PIN)
        case 16:
            idx = OPL1000_IO16_PIN;
            break;
#endif
#if defined(OPL1000_IO17_PIN)
        case 17:
            idx = OPL1000_IO17_PIN;
            break;
#endif
#if defined(OPL1000_IO18_PIN)
        case 18:
            idx = OPL1000_IO18_PIN;
            break;
#endif
#if defined(OPL1000_IO19_PIN)
        case 19:
            idx = OPL1000_IO19_PIN;
            break;
#endif
#if defined(OPL1000_IO20_PIN)
        case 20:
            idx = OPL1000_IO20_PIN;
            break;
#endif
#if defined(OPL1000_IO21_PIN)
        case 21:
            idx = OPL1000_IO21_PIN;
            break;
#endif
#if defined(OPL1000_IO22_PIN)
        case 22:
            idx = OPL1000_IO22_PIN;
            break;
#endif
#if defined(OPL1000_IO23_PIN)
        case 23:
            idx = OPL1000_IO23_PIN;
            break;
#endif
        default:
            break;
    }

    return (idx);
}

/*****************************************************************************
 * Public Functions
 ****************************************************************************/

PLUM_PUBLIC
plum_s32 plum_hal_uart_init(plum_u32 id, plum_hal_uart_cof_t *config)
{
    plum_s32 rc = PLUM_ECODE_OK;

    do {
        if (!PLUM_HAL_ID_IS_UART(id)) {
            rc = PLUM_ECODE_EPARA;
            LOG_E("the id is not a uart id");
            break;
        }

        if (!config) {
            LOG_E("the config pointer is null");
            rc = PLUM_ECODE_INVALID;
            break;
        }

        T_OPL1000_uart uart = {UART_IDX_MAX};
        uart.index          = hal_opl1x_uart_idx(id);
        uart.tx             = hal_opl1x_uart_gpio_pin(config->txpin_id);
        uart.rx             = hal_opl1x_uart_gpio_pin(config->rxpin_id);
        uart.rts            = BLANK_PIN;
        uart.cts            = BLANK_PIN;
        uart.baudrate       = config->baudrate;
        uart.bits           = hal_opl1x_uart_databits(config->databit);
        uart.parity         = hal_opl1x_uart_parity(config->parity);
        uart.stopBit        = hal_opl1x_uart_stopbit(config->stopbit);
        uart.flowCtl        = hal_opl1x_uart_flowctl(config->flowctrl);
        rc                  = Hal_PinMux_Uart_Init(&uart);
        if (rc) {
            LOG_E("Hal_PinMux_Uart_Init err,rc: %d", rc);
            rc = PLUM_ECODE_EIO;
        }
    } while (0);

    return (rc);
}

PLUM_PUBLIC
plum_s32 plum_hal_uart_send(plum_u32 id, const plum_void *data, plum_u16 cnt)
{
    plum_s32 rc = PLUM_ECODE_OK;

    do {
        if (!PLUM_HAL_ID_IS_UART(id)) {
            rc = PLUM_ECODE_EPARA;
            LOG_E("the id is not a uart id");
            break;
        }

        if (!data) {
            rc = PLUM_ECODE_INVALID;
            LOG_E("the data pointer is null");
            break;
        }

        E_UartIdx_t idx = hal_opl1x_uart_idx(id);
        if (idx != UART_IDX_MAX) {
            LOG_E("the hal not support the uart");
            rc = PLUM_ECODE_INVALID;
            break;
        }

        plum_u16 loop  = 0;
        plum_u8 *value = (plum_u8 *)data;
        for (loop = 0; loop < cnt; loop++) {
            rc += Hal_Uart_DataSend(idx, *value);
            value++;
        }

    } while (0);

    return (rc);
}

PLUM_PUBLIC
plum_s32 plum_hal_uart_recv(plum_u32 id, void *data, plum_u16 size,
                            plum_u32 timeout)
{
    plum_s32 rc = PLUM_ECODE_OK;

    do {
        if (!PLUM_HAL_ID_IS_UART(id)) {
            rc = PLUM_ECODE_EPARA;
            LOG_E("the id is not a uart id");
            break;
        }

        if (!data) {
            rc = PLUM_ECODE_INVALID;
            LOG_E("the data pointer is null");
            break;
        }

        E_UartIdx_t idx = hal_opl1x_uart_idx(id);
        if (idx != UART_IDX_MAX) {
            LOG_E("the hal not support the uart");
            rc = PLUM_ECODE_INVALID;
            break;
        }

        rc = Hal_Uart_DataRecvTimeOut(idx, data, timeout);

    } while (0);

    return (rc);
}

/****************************************************************************/
/*                                                                          */
/*  End of file.                                                            */
/*                                                                          */
/****************************************************************************/
